const modal = require('./modal')
const schema = modal.schema
const padStart = require('lodash').padStart

/**
 * 获取Parse对象的对应属性
 * @param sources {object} Parse对象
 * @param attributes {array} 需要获取的属性列表
 * @returns {{}}
 */
const mapAttributes = (sources, attributes) => {
  const obj = {}
  attributes.forEach((key) => {
    obj[key] = sources.get(key)
  })
  obj.id = sources.id
  return obj
}
/**
 * 是否为手机号码
 * @param mobile {string | number} 需要检测的值
 * @returns {boolean}
 */
const isMobile = (mobile) => {
  const reg = /^1[3|5][0-9]\d{4,8}$/
  return reg.test(mobile)
}
/**
 * 获取下级会员
 * @param member {object} 当前会员
 * @param count {number} 需要查找的深度
 * @returns {Promise.<Array>} 会员的ID列表
 */
const getSubMembers = async (member, count) => {
  let container = []
  let deep = 1
  /**
   *
   * @param reMember {object} 会员
   * @param reCount {number} 需要查找的深度
   * @param reDeep {number} 当前深度
   * @returns {Promise.<void>}
   */
  const recursive = async (reMember, reCount, reDeep) => {
    if (reCount > 0) {
      const query = schema.member().query()
      query.equalTo('parent', reMember)
      query.equalTo('status', 1)
      const members = await query.find()
      container = container.concat(members.map((item) => {
        return {
          id: item.id,
          level: item.get('level'),
          deep: reDeep
        }
      }))
      if (members.length > 0) {
        for (let i = 0, len = members.length; i < len; i++) {
          await recursive(members[i], reCount - 1, reDeep + 1)
        }
      }
    }
  }
  await recursive(member, count, deep)
  return container
}
/**
 * 合计多个会员的群数量
 * @param memberIds {array} 会员的ID列表
 * @returns {Promise.<number>}
 */
const countGroupNumbers = async (memberIds) => {
  let groupCount = 0
  if (memberIds.length > 0) {
    const members = memberIds.map((id) => {
      const member = schema.member()
      member.id = id
      return member
    })
    const groupQuery = schema.group().query()
    groupQuery.equalTo('status', 1)
    groupQuery.containedIn('member', members)
    groupCount = await groupQuery.count()
  }
  return groupCount
}

/**
 * 时间段
 */
class TimeRange {
  constructor () {
    this.now = new Date()  // 当前时间
    this.dayOfWeek = this.now.getDay() // 本周的第几天
    this.day = this.now.getDate()  // 本月的第几天
    this.month = this.now.getMonth() // 当前月
    this.year = this.now.getFullYear() // 当前年
    this.preMonthDate = new Date()  // 上月
    this.preMonthDate.setDate(1)  // 将日期设为月的第一天
    this.preMonthDate.setMonth(this.preMonthDate.getMonth() - 1)  // 将月份设为当前月份的前一月
    this.preMonthYear = this.preMonthDate.getFullYear()  // 上一月的年份
    this.preMonth = this.preMonthDate.getMonth()  // 上一月
  }

  /**
   * 获取指定月份的天数
   * @param month {number} 指定的月份
   * @returns {number} 天数
   */
  getMonthDays (month) {
    const start = new Date(this.year, month, 1)
    const end = new Date(this.year, month + 1, 1)
    return (end - start) / (1000 * 60 * 60 * 24)
  }

  /**
   * 当天时间段
   * @returns {[*,*]}
   */
  thisDay () {
    const start = new Date(this.year, this.month, this.day)
    const end = new Date(this.year, this.month, this.day, 23, 59, 59)
    return [start, end]
  }
  /**
   * 前一天时间段
   * @returns {[*,*]}
   */
  lastDay () {
    const start = new Date(this.year, this.month, this.day - 1)
    const end = new Date(this.year, this.month, this.day - 1, 23, 59, 59)
    return [start, end]
  }

  /**
   * 本周时间段
   * @returns {[*,*]}
   */
  thisWeek () {
    const start = new Date(this.year, this.month, this.day - this.dayOfWeek)
    const end = this.now
    return [start, end]
  }

  /**
   * 上周时间段
   * @returns {[*,*]}
   */
  lastWeek () {
    const start = new Date(this.year, this.month, this.day - this.dayOfWeek - 7)
    const end = new Date(this.year, this.month, this.day - this.dayOfWeek, 23, 59, 59)
    return [start, end]
  }

  /**
   * 本月时间段
   * @returns {[*,*]}
   */
  thisMonth () {
    const start = new Date(this.year, this.month, 1)
    const end = this.now
    return [start, end]
  }

  /**
   * 上月时间段
   * @returns {[*,*]}
   */
  lastMonth () {
    const start = new Date(this.preMonthYear, this.preMonth, 1)
    const end = new Date(this.preMonthYear, this.preMonth, this.getMonthDays(this.preMonth), 23, 59, 59)
    return [start, end]
  }

  /**
   * 指定最近天数的时间段
   * @param day {number} 最近多少天
   * @returns {[*,*]}
   */
  recentDays (day) {
    const start = new Date(this.year, this.month, this.day - day)
    const end = new Date(this.year, this.month, this.day - 1, 23, 59, 59)
    return [start, end]
  }

  /**
   * 最近天数时间段，包含当天
   * @param day
   * @returns {[*,*]}
   */
  currentDays (day) {
    const start = new Date(this.year, this.month, this.day - day + 1)
    const end = new Date(this.year, this.month, this.day, 23, 59, 59)
    return [start, end]
  }

  /**
   * 最近时间范围
   * @param startDay {number} 几天前
   * @param limit {number} 天数
   * @returns {[*,*]}
   */
  recentRange (startDay, limit) {
    const start = new Date(this.year, this.month, this.day - startDay)
    const end = new Date(this.year, this.month, this.day - 1 - startDay + limit, 23, 59, 59)
    return [start, end]
  }
}

/**
 * 不足两位，在前面补0
 * @param value
 * @returns {string}
 */
const padStartByZero = (value) => {
  return padStart(value, 2, '0')
}
/**
 * 生成编码
 * @returns {string}
 */
const generateSheet = () => {
  const date = new Date()
  return `${padStartByZero(date.getYear())}${padStartByZero(date.getMonth())}${padStartByZero(date.getDay())}${padStartByZero(date.getHours())}${padStartByZero(date.getMinutes())}${padStartByZero(date.getSeconds())}${padStartByZero(date.getMilliseconds())}${padStartByZero(parseInt(Math.random() * 100, 10))}`
}

/**
 * 设置对象对应的键值
 * @param obj {object} 需要设置的对象
 * @param keyString {string} 需要设置的key
 * @param val 需要设置的值
 */
const setValByKey = (obj, keyString, val) => {
  const keyArray = keyString.split('.') // 分解key,将字符串转换为数组
  const len = keyArray.length
  let current = obj  // 当前需要设置值的对象

  if (len > 0) {
    keyArray.forEach((key, index) => {
      if (typeof current[key] === 'undefined') {  // 如果属性不存在
        if (index < len - 1) {  // 如果不是最后一个属性,则设置为空对象
          current[key] = {}
        } else {  // 否则,设置值
          current[key] = val
        }
      } else if (index + 1 === len) {  // 如果属性原来已经定义,在最后一个属性设置值
        current[key] = val
      }
      current = current[key]  // 更新当前需要设置值的对象
    })
  }
}

/**
 * 获取parse object 深层属性
 * @param parseObj {object} parse 对象
 * @param key {string} keys, 如key1.key2.key3
 * @param defaultVal {*} 当属性不存在时，默认的返回值
 * @returns {*}
 */
const getParseObjectDeep = (parseObj, key, defaultVal = undefined) => {
  const keys = key.split('.')
  let temp = parseObj
  for (let i = 0, len = keys.length; i < len; i++) {
    if (temp) {
      temp = temp.get(keys[i])
    } else {
      break
    }
  }
  return typeof temp === 'undefined' ? defaultVal : temp
}
/**
 * 获取parseObj 自定义映射
 * @param parseObj {object} parse 对象
 * @param keyMap {array || object} 键映射
 * @returns {{}}
 */
const getAttributesMap = (parseObj, keyMap) => {
  const obj = {}
  let attributes = keyMap
  if (Array.isArray(keyMap)) {
    attributes = keyMap.reduce((prev, cur) => {
      prev[cur] = cur
      return prev
    }, {})
  }
  Object.keys(attributes).forEach((key) => {
    setValByKey(obj, key, getParseObjectDeep(parseObj, attributes[key]))
  })
  obj.id = parseObj.id
  return obj
}
/**
 * 获取 parse 数组的属性
 * @param parseArr {array} parse 对象数组
 * @param keyMap {array || object}
 * @param fn
 */
const mapArrayAttributes = (parseArr, keyMap, fn) => {
  return parseArr.map((item, index) => {
    const result = getAttributesMap(item, keyMap)
    return fn ? fn(result, item, index) : result
  })
}
/**
 * 获取指定日期的字符串`2017-8-6`
 * @param date {date} 默认为当天
 * @returns {string}
 */
const getDayString = (date = new Date()) => {
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  return `${year}-${month}-${day}`
}

module.exports = {
  mapAttributes,
  isMobile,
  getSubMembers,
  countGroupNumbers,
  TimeRange,
  padStartByZero,
  generateSheet,
  setValByKey,
  getParseObjectDeep,
  getAttributesMap,
  mapArrayAttributes,
  getDayString
}
